/*!
 * \file set_relation_visitor_base.h
 *
 * \brief Interface for concrete visitors of Set and Relation classes.
 *
 *
 * \date Started: 6/8/2010
 * \date Last Modified: 7/6/2010
 * \authors Ian Craig
 */

#ifndef SET_RELATION_H
#define SET_RELATION_H

#include <iegenlib/iegenlib.h>

#include <stack>
using std::stack;

namespace iegenlib{

/*!
 * \class SRVisitor
 * \brief The base set/relation visitor class
 *
 * The base class for traversing the symbol table tree. Unfortunately (for now)
 * due to the way that the symbol table and its related classes were designed
 * (not as an AST) the defaultIn and defaultOut methods are a bit limited in the
 * information that they are given to work with. The classes involved however
 * do now provide a lot of information when inside a set of nodes that are
 * involved with them (i.e the in/case/out nodes)
 *
 * All of the other visitors that are going to traverse the Symbol table should
 * extend off of this class as the actual traversal is already built into this
 * class.
 *
 * OF SPECIAL NOTE (the same as the AST): If a case method is overriden, so are
 * all the apply methods that are typically called from there. So if you must
 * override a case method, be aware that you will have to reimplement the
 * apply
 */
class SRVisitor{
public:

  ///Used for general tasks to be done going into every visited node
  virtual void defaultIn() = 0;

  ///Used for general tasks to be done going out of every visited node
  virtual void defaultOut() = 0;

//Set methods
  /*!
   * hook method called by the SetCase method for sets
   * @param set Set that calls the case method
   */
  virtual inline void SetIn(const Set* set){defaultIn();}

  /*!
   * hook method called by apply methods for set
   * @param set Set that calls the case method
   */
  virtual void SetCase(const Set* set);

  /*!
   * hook method called by the SetCase method for sets
   * @param set Set that calls the case method
   */
  virtual inline void SetOut(const Set* set){defaultOut();}

//Relation methods
  /*!
   * hook method called by the RelationCase method for relations
   * @param relation Relation that calls the case method
   */
  virtual inline void RelationIn(const Relation* relation){defaultIn();}

  /*!
   * hook method called by apply methods for relation
   * @param relation Relation that calls the case method
   */
  virtual void RelationCase(const Relation* relation);

  /*!
   * hook method called by the relationCase method for relations
   * @param relation Relation that calls the case method
   */
  virtual inline void RelationOut(const Relation* relation){defaultOut();}

//SparseConstraints
    /*!
   * hook method called by the SparseConstraintsCase method for SparseConstraints
   * @param spcon SparseConstraints that calls the case method
   */
  virtual inline void SparseConstraintsIn(const SparseConstraints* spcon){defaultIn();}

  /*!
   * hook method called by apply methods for SparseConstraint
   * @param spcon SparseConstraints that calls the case method
   */
  virtual void SparseConstraintsCase(const SparseConstraints* spcon);

  /*!
   * hook method called by the SparseConstraintsCase method for SparseConstraints
   * @param spcon Relation that calls the case method
   */
  virtual inline void SparseConstraintsOut(const SparseConstraints* spcon){defaultOut();}

//SymbolTable methods
  /*!
   * hook method called by the SymbolTableCase method for symbol tables
   * @param symboltable Symbol table that calls the case method
   */
  virtual inline void SymbolTableIn(SymbolTable* symboltable){defaultIn();}

  /*!
   * hook method called by apply methods for symbol table
   * @param symboltable Symbol table that calls the case method
   */
  virtual void SymbolTableCase(SymbolTable* symboltable);

  /*!
   * hook method called by the SymbolTableCase method for symbol tables
   * @param symboltable Symbol table that calls the case method
   */
  virtual inline void SymbolTableOut(SymbolTable* symboltable){defaultOut();}

//SRConjunction methods
  /*!
   * hook method called by the SRConjunctionCase method for SRConjunctions
   * @param SRConj conjunction that calls the case method
   */
  virtual inline void SRConjunctionIn(const SRConjunction* SRConj){defaultIn();}

  /*!
   * hook method called by apply methods for SRConjunction
   * @param SRConj conjunction that calls the case method
   */
  virtual void SRConjunctionCase(const SRConjunction* SRConj);

  /*!
   * hook method called by the SRConjunctionCase method for SRConjunctions
   * @param SRConj conjunction that calls the case method
   */
  virtual inline void SRConjunctionOut(const SRConjunction* SRConj){defaultOut();}

//SREquality methods
  /*!
   * hook method called by the SREqualityCase method for SREqualities
   * @param eq SREquality that calls the case method
   */
  virtual inline void SREqualityIn(const SREquality* eq){defaultIn();}

  /*!
   * hook method called by the SREqualityCase method for SREqualities
   * @checks whether the tuple variable of the i-th position in the ExpVec
   * vec param for OldSymTable exists in the ExpVec of the new SymTable
   */
  virtual int is_tupleVar(ExpVec vec, int i){}

  /*!
   * hook method called by apply methods for SREquality
   * @param eq SREquality that calls the case method
   */
  virtual void SREqualityCase(const SREquality* eq);

  /*!
   * hook method called by the SREqualityCase method for SREqualities
   * @param eq SREquality that calls the case method
   */
  virtual inline void SREqualityOut(const SREquality* eq){defaultOut();}

//SRInequality methods
  /*!
   * hook method called by the SRInequalityCase method for SRInequalities
   * @param ineq SRInequality that calls the case method
   */
  virtual inline void SRInequalityIn(const SRInequality* ineq){defaultIn();}

  /*!
   * hook method called by apply methods for SRInequality
   * @param ineq SRInequality that calls the case method
   */
  virtual void SRInequalityCase(const SRInequality* ineq);

  /*!
   * hook method called by the SRInequalityCase method for SRInequalities
   * @param ineq SRInequality that calls the case method
   */
  virtual inline void SRInequalityOut(const SRInequality* ineq){defaultOut();}

//ExpVecIn methods
  /*!
   * hook method called by the ExpVecCase method for ExpVecs
   * @param vec ExpVec that calls the case method
   */
  virtual inline void ExpVecIn(const ExpVec* vec){defaultIn();}

  /*!
   * hook method called by apply methods for ExpVec
   * @param vec ExpVec that calls the case method
   */
  virtual void ExpVecCase(const ExpVec* vec);

  /*!
   * hook method called by the ExpVecCase method for ExpVecs
   * @param vec ExpVec that calls the case method
   */
  virtual inline void ExpVecOut(const ExpVec* vec){defaultOut();}

//STE methods
  /*!
   * hook method called by the STECase method for STEs
   * @param ste STE that calls the case method
   */
  virtual inline void STEIn(STE* ste){defaultIn();}

  /*!
   * hook method called by apply methods for ExpVec
   * @param ste STE that calls the case method
   */
  virtual void STECase(STE* ste);

  /*!
   * hook method called by the ExpVecCase method for ExpVecs
   * @param ste STE that calls the case method
   */
  virtual inline void STEOut(STE* ste){defaultOut();}

//TupleVar methods
  /*!
   * hook method called by the TupleVarCase method for TupleVars
   * @param tupvar TupleVar that calls the case method
   */
  virtual inline void TupleVarIn(TupleVar* tupvar){defaultIn();}

  /*!
   * hook method called by apply methods for TupleVar
   * @param tupvar TupleVar that calls the case method
   */
  virtual void TupleVarCase(TupleVar* tupvar);

  /*!
   * hook method called by the TupleVarCase method for TupleVars
   * @param tupvar TupleVar that calls the case method
   */
  virtual inline void TupleVarOut(TupleVar* tupvar){defaultOut();}

//ExistVar methods
  /*!
   * hook method called by the ExistVarCase method for ExistVars
   * @param exists ExistVar that calls the case method
   */
  virtual inline void ExistVarIn(ExistVar* exists){defaultIn();}

  /*!
   * hook method called by apply methods for ExistVar
   * @param exists ExistVar that calls the case method
   */
  virtual void ExistVarCase(ExistVar* exists);

  /*!
   * hook method called by the ExistVarCase method for ExistVars
   * @param exists ExistVar that calls the case method
   */
  virtual inline void ExistVarOut(ExistVar* exists){defaultOut();}

//SymConst methods
  /*!
   * hook method called by the SymConstCase method for SymConsts
   * @param symbolic SymConst that calls the case method
   */
  virtual inline void SymConstIn(SymConst* symbolic){defaultIn();}

  /*!
   * hook method called by apply methods for SymConst
   * @param symbolic SymConst that calls the case method
   */
  virtual void SymConstCase(SymConst* symbolic);

  /*!
   * hook method called by the SymConstCase method for SymConsts
   * @param symbolic SymConst that calls the case method
   */
  virtual inline void SymConstOut(SymConst* symbolic){defaultOut();}

//UFCall methods
  /*!
   * hook method called by the UFCallCase method for UFCalls
   * @param ufcall UFCall that calls the case method
   */
  virtual inline void UFCallIn(UFCall* ufcall){defaultIn();}

  /*!
   * hook method called by apply methods for UFCall
   * @param ufcall UFCall that calls the case method
   */
  virtual void UFCallCase(UFCall* ufcall);

  /*!
   * hook method called by the UFCallCase method for UFCalls
   * @param ufcall UFCall that calls the case method
   */
  virtual inline void UFCallOut(UFCall* ufcall){defaultOut();}

//TupleType methods
  /*!
   * hook method called by the TupleTypeCase method for TupleTypes
   * @param TupleType TupleType that calls the case method
   */
  virtual inline void TupleTypeIn(const TupleType* tupletype){defaultIn();}

  /*!
   * hook method called by apply methods for TupleType
   * @param TupleType TupleType that calls the case method
   */
  virtual void TupleTypeCase(const TupleType* tupletype);

  /*!
   * hook method called by the TupleTypeCase method for TupleTypes
   * @param TupleType TupleType that calls the case method
   */
  virtual inline void TupleTypeOut(const TupleType* tupletype){defaultOut();}
};

/*!
 *  \class VisitorTester
 *
 *  \brief A wrapper class for SRVisitor for testing
 */
class VisitorTester: public SRVisitor{
public:
  inline void defaultIn(){}
  inline void defaultOut(){}
  
  inline void SetIn(Set*){node.push("set");}

  inline void RelationIn(Relation*){node.push("relation");}

  inline void SymbolTableIn(SymbolTable*){node.push("symtable");}

  inline void SRConjunctionIn(SRConjunction*){node.push("conj");}

  inline void SREqualityIn(SREquality*){node.push("eq");}

  inline void SRInequalityIn(SRInequality*){node.push("ineq");}

  inline void ExpVecIn(ExpVec*){node.push("expvec");}

  inline void TupleVarIn(TupleVar*){node.push("tupvar");}

  inline void ExistVarIn(ExistVar*){node.push("exist");}

  inline void SymConstIn(SymConst*){node.push("sym");}

  inline void UFCallIn(UFCall*){node.push("ufcall");}

  inline stack<string> getNodeStack(){return node;}

private:
  stack<string> node;
};

}//end namespace iegenlib

#endif
